package com.coincalf.wallet.task.syncblock;

import com.coincalf.framework.enums.RechargeStatus;
import com.coincalf.framework.utils.DateUtil;
import com.coincalf.wallet.blockchain.RippleService;
import com.coincalf.wallet.blockchain.bean.xrp.XrpTxs;
import com.coincalf.wallet.entity.AddressPool;
import com.coincalf.wallet.entity.CoinRecharge;
import com.coincalf.wallet.entity.SyncBlockHeight;
import com.coincalf.wallet.entity.UserMemo;
import com.coincalf.wallet.service.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import wf.bitcoin.javabitcoindrpcclient.BitcoinJSONRPCClient;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;


/**
 * XRP充币 只需要交易所提供一个充币地址即可 所有用户充XRP到该地址 但是必须附加不同的tag
 *
 * @author czj
 * @date 2019/9/11 7:27 PM
 */
@Component
@EnableScheduling
@Transactional(rollbackFor = Exception.class)
public class SyncXrpTxs {

    private static final Logger log = LoggerFactory.getLogger(SyncXrpTxs.class);
    private static final BigDecimal XRP_EXCHANGE = BigDecimal.valueOf(1000000L);

    @Autowired
    private SyncBlockHeightService syncBlockHeightService;
    @Autowired
    private CoinRechargeService rechargeService;
    @Autowired
    private AddressPoolService addressPoolService;
    @Autowired
    private UserMemoService userMemoService;


    //@Scheduled(cron = "0/10 * * * * ?")
    public void syncTask() {
        log.info("开始执行XRP区块扫描任务 当前时间={}", DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
        long startTime = System.currentTimeMillis();
        //从数据库获取已经同步的区块高度
        SyncBlockHeight xrpSyncedBlockHeight = syncBlockHeightService.selectOneByCoinName("XRP");
        if (xrpSyncedBlockHeight == null || xrpSyncedBlockHeight.getSyncedBlockHeight() == null) {
            log.warn("无法找到XRP同步缓存高度");
            return;
        } else if (xrpSyncedBlockHeight.getStatus() == 0) {
            log.info("本次XRP同步状态已关闭");
            return;
        }
        Integer height = xrpSyncedBlockHeight.getSyncedBlockHeight();
        if (height == null || height == 0) {
            height = -1;
        }

        //XRP充币地址
        String xrpAddress;
        AddressPool addressPool = addressPoolService.selectAddress(xrpSyncedBlockHeight.getCoinId());
        if (addressPool == null) {
            log.warn("数据库ex_wallet-address_pool表暂未配置XRP充币地址信息");
            return;
        } else {
            xrpAddress = addressPool.getAddress();
        }

        //查询地址指定区块高度之间([height, +00])的所有交易纪录
        List<XrpTxs.Transactions> txs = RippleService.getTxs(xrpAddress, height, -1L);

        //判断该记录是否已经存在
        for (XrpTxs.Transactions tx : txs) {
            XrpTxs.Transactions.Tx txInfo = tx.getTx();
            //只处理充币交易纪录 转账交易不做处理
            if (txInfo.getToAddress().equals(xrpAddress)) {
                CoinRecharge coinRecharge = new CoinRecharge();
                coinRecharge.setFromAddress(txInfo.getFromAddress());
                coinRecharge.setAddress(txInfo.getToAddress());
                String tag = txInfo.getTag();
                try {
                    long tagL = Long.parseLong(tag);
                    UserMemo userMemo = userMemoService.selectOneByTag(tagL);
                    coinRecharge.setUserId(userMemo.getUserId());
                } catch (NumberFormatException e) {
                    log.warn("tag不是long类型 可能非用户充币或者其他充币来源 tag={}", tag);
                    continue;
                }
                coinRecharge.setMemo(tag);
                coinRecharge.setTxid(tx.getTx().getHash());
                coinRecharge.setCoinId(xrpSyncedBlockHeight.getCoinId());
                coinRecharge.setCoinName("XRP");
                BigDecimal amount = BigDecimal.ZERO;
                if (tx.getMeta().getTransactionResult().equals("tesSUCCESS")) {
                    //交易成功
                    coinRecharge.setStatus(RechargeStatus.PENDING.getCode());
                    coinRecharge.setCollected(1);
                    amount = tx.getMeta().getDeliveredAmount().divide(XRP_EXCHANGE, 6, RoundingMode.HALF_DOWN);
                } else {
                    //失败的交易
                    coinRecharge.setStatus(-1);
                    coinRecharge.setCollected(0);
                }
                coinRecharge.setMum(amount);
                BigDecimal fee = txInfo.getFee().divide(XRP_EXCHANGE, 6, RoundingMode.DOWN);
                coinRecharge.setFee(fee);
                coinRecharge.setNum(amount.add(fee));
                coinRecharge.setConfirm(1);
                coinRecharge.setBlockNumber(txInfo.getBlockHeight());
                coinRecharge.setCreated(new Date());
                coinRecharge.setLastUpdateTime(new Date());
                CoinRecharge exits = rechargeService.selectOneByCoinIdAndTxIdAndToAddress(
                        coinRecharge.getCoinId(),
                        coinRecharge.getTxid(),
                        coinRecharge.getAddress()
                );
                if (exits == null) {
                    rechargeService.insert(coinRecharge);
                    log.info("XRP充币交易写入成功 txId={} fromAddress={}", txInfo.getHash(), txInfo.getFromAddress());
                } else {
                    log.warn("XRP充币交易已存在 txId={} fromAddress={}", txInfo.getHash(), txInfo.getFromAddress());
                }
            }

            //更新已查询的区块高度
            if (txInfo.getBlockHeight() > height) {
                height = txInfo.getBlockHeight();
            }
        }

        //更新已同步的区块高度
        xrpSyncedBlockHeight.setSyncedBlockHeight(height);
        xrpSyncedBlockHeight.setLastUpdateTime(new Date());
        syncBlockHeightService.updateById(xrpSyncedBlockHeight);

        //任务结束
        long endTime = System.currentTimeMillis();
        long spent = (endTime - startTime) / 1000;
        log.info("本次XRP区块同步任务结束，耗时={}秒 已扫描区块高度={}", spent, height);
    }

}

